//
// Created by 17775 on 2024/11/1.
//

#ifndef RAYCI_LIVEMODE_ANALYSIS_H
#define RAYCI_LIVEMODE_ANALYSIS_H

#include <QString>
#include "RayCiPro_C.h"
#include "../RayCi/LiveMode.h"
#include <QMap>
#include <thread>
#include <QObject>

using DataVariant = std::variant<double, QString>;

struct StatisticResult {
    double dNumber = 0;
    double dPower = 0;
    double dPeak = 0;
    double dPosX = 0;
    double dPosY = 0;
    double dSNR = 0;
};

struct ThresholdResult {
    double dEffectivePower = 0;
    double dPowerRatio = 0;
    double dEffectiveArea = 0;
    double dMeanIntensity = 0;
    double dFlatness = 0;
    double dUniformity = 0;
    double dEdgeSteepness = 0;
};

struct SecondMomentsResult {
    double dCentroidX = 0;
    double dCentroidY = 0;
    double dWidthLabX = 0;
    double dWidthLabY = 0;
    double dMajor = 0;
    double dMinor = 0;
    double dAzimuthAngle = 0;
    double dEllipticity = 0;
    double dEccentricity = 0;
    double dArea = 0;
    double dPowerFraction = 0;
};

struct GaussResult {
    double dCentroidX = 0;
    double dCentroidY = 0;
    double dWidthLabX = 0;
    double dWidthLabY = 0;
    double dMajor = 0;
    double dMinor = 0;
    double dAzimuthAngle = 0;
    double dEllipticity = 0;
    double dEccentricity = 0;
    double dArea = 0;
    double dPowerFraction = 0;
    double dGFI = 0;
    double dCorrelation = 0;
};

struct PlateauResult {
    double dCentroidX = 0;
    double dCentroidY = 0;
    double dMajor = 0;
    double dMinor = 0;
    double dAzimuthAngle = 0;
    double dEllipticity = 0;
    double dEccentricity = 0;
    double dArea = 0;
    double dUniformity = 0;
    double dRoughness = 0;
    double dPowerFraction = 0;
    double dGFI =0;
    double dCorrelation = 0;
    double dTopHatFactor = 0;
};

struct SimpleGeometry {
    double dCentroidX = 0;
    double dCentroidY = 0;
    double dMajor = 0;
    double dMinor = 0;
    double dAzimuthAngle = 0;
    double dEllipticity = 0;
    double dEccentricity = 0;
    double dArea = 0;
    double dPowerFraction = 0;
};

struct KnifeEdge {
    double dMajor = 0;
    double dMinor = 0;
    double dAzimuthAngle = 0;
    double dEllipticity = 0;
    double dEccentricity = 0;
};

class LiveMode_Analysis : public QObject {
Q_OBJECT

signals:
//    void getNewResult(std::map<std::string, DataVariant>);
    void getNewStatistic(StatisticResult statisticResult);
    void getNewThreshold(StatisticResult statisticResult, ThresholdResult thresholdResult);
    void getNewSecondMoments(StatisticResult statisticResult, SecondMomentsResult secondMomentsResult);
    void getNewGauss(StatisticResult statisticResult, GaussResult gaussResult);
    void getNewSuperGauss(StatisticResult statisticResult, GaussResult gaussResult);
    void getNewPlateau(StatisticResult statisticResult, PlateauResult plateauResult);
    void getNewSimpleGeometry(StatisticResult statisticResult, SimpleGeometry simpleGeometry);
    void getNewKnifeEdge(StatisticResult statisticResult, KnifeEdge knifeEdge);
    void getNewMovingSlit(StatisticResult statisticResult, KnifeEdge knifeEdge);
    void getNewDropdown(StatisticResult statisticResult, KnifeEdge knifeEdge);

public:
    int _nDocIdLive = 0;
    explicit LiveMode_Analysis(const int &docId) : _nDocIdLive(docId) {}
    ~LiveMode_Analysis() override;
    std::thread m_resultThread;
    std::atomic<bool> _isGettingNewResultData = false;
    void getData();
    void stopGetData();
//    std::map<std::string, DataVariant> fetchData();
    void fetchData();
    MethodsType methodsType = MethodsType::None;

    // Combined Statistic
    double getCombinedStatisticMinimum(int32_t nColumn = 0, bool bOnlyIlluminated = false);
    QString getCombinedStatisticMinimumUnit();
    double getCombinedStatisticPeak(int32_t nColumn = 0, bool bOnlyIlluminated = false);
    QString getCombinedStatisticPeakUnit();
    double getCombinedStatisticPeakPos_X(int32_t nColumn = 0, bool bOnlyIlluminated = false);
    double getCombinedStatisticPeakPos_Y(int32_t nColumn = 0, bool bOnlyIlluminated = false);
    QString getCombinedStatisticPeakPosUnit();
    double getCombinedStatisticAverage(int32_t nColumn = 0, bool bOnlyIlluminated = false);
    QString getCombinedStatisticAverageUnit();
    double getCombinedStatisticRMS(int32_t nColumn = 0, bool bOnlyIlluminated = false);
    QString getCombinedStatisticRMSUnit();
    double getCombinedStatisticStDev(int32_t nColumn = 0, bool bOnlyIlluminated = false);
    QString getCombinedStatisticStDevUnit();
    double getCombinedStatisticPower(int nColumn, bool bOnlyIlluminated);
    bool combinedStatisticPowerIsValid(int nColumn, bool bOnlyIlluminated);
    QString getCombinedStatisticPowerUnit();

    // Statistic
    StatisticResult getStatistic(int32_t nColumn = 0, bool bOnlyIlluminated = true);
    double getStatisticMinimum(int32_t nColumn = 0, bool bOnlyIlluminated = false);
    QString getStatisticPowerUnit(int32_t nColumn = 0, bool bOnlyIlluminated = false);
    QString getStatisticMinimumUnit();
    QString getStatisticPeakUnit();
    QString getStatisticPeakPosUnit();

    // Threshold
    ThresholdResult getThresholdResult(int32_t nColumn = 0);

    // SecondMoments
    SecondMomentsResult getSecondMomentResult(int32_t nColumn = 0);

    // Fit Gauss
    GaussResult getGaussResult(int32_t nColumn = 0);

    // Fit SuperGauss
    GaussResult getSuperGaussResult(int32_t nColumn = 0);

    // Plateau
    PlateauResult getPlateauResult(int32_t nColumn = 0);

    // SimpleGeometry
    SimpleGeometry getSimpleGeometryResult(int32_t nColumn = 0);

    // Area

    // KnifeEdge
    KnifeEdge getKnifeEdgeResult(int32_t nColumn = 0);

    // MovingSlit
    KnifeEdge getMovingSlitResult(int32_t nColumn = 0);

    // Dropdown
    KnifeEdge getDropdownResult(int32_t nColumn = 0);

private:

};


#endif //RAYCI_LIVEMODE_ANALYSIS_H
